package com.abou.utils.common;

import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import javax.servlet.http.HttpServletRequest;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import org.apache.log4j.Logger;
import com.abou.mvc.controller.ControllerUtils;

/**
 * The class containing utility methods for dates
 * 
 * @author khalid
 */
public final class DateUtils {
  
  private static final Logger LOGGER = Logger.getLogger(DateUtils.class);
  
  /**
   * The max hour value
   */
  public static final int MAX_HOUR = 23;
  
  /**
   * The max minute value
   */
  public static final int MAX_MINUTE = 59;
  
  /**
   * The max second value
   */
  public static final int MAX_SECOND = 59;
  
  /**
   * The max millisecond value
   */
  public static final int MAX_MS = 999;
  
  /**
   * The value used to convert hours to minutes and vice-versa.
   */
  public static final int HOURS_MINUTES_CONVERTER_VALUE = 60;
  
  /**
   * The GMT time zone name.
   */
  public static final String GMT_TIME_ZONE = "GMT";
  
  /**
   * A factory used to create XML gregorian calendar
   */
  private static DatatypeFactory datatypeFactory;
  
  static {
    
    try {
      datatypeFactory = DatatypeFactory.newInstance();
    } catch (DatatypeConfigurationException ex) {
      LOGGER.debug("Cannot create data type factory");
    }
  }
  
  /**
   * The private constructor to prevent the class from being instantiated
   */
  private DateUtils() {

    super();
  }
  
  /**
   * Returns the date object corresponding to the passed calendar
   * 
   * @param calendar A calendar
   * @return A date
   */
  public static Date getDate(Calendar calendar) {

    Date date = null;
    
    if (calendar != null) {
      
      date = calendar.getTime();
    }
    
    return date;
  }
  
  /**
   * Returns the date object corresponding to the passed XML calendar
   * 
   * @param calendar A calendar
   * @return A date
   */
  public static Date getDate(XMLGregorianCalendar calendar) {

    Date date = null;
    
    if (calendar != null) {
      
      date = calendar.toGregorianCalendar().getTime();
    }
    
    return date;
  }
  
  /**
   * Returns the calendar object corresponding to the passed date
   * 
   * @param date A date
   * @return The corresponding calendar
   */
  public static XMLGregorianCalendar getXmlCal(Date date) {

    XMLGregorianCalendar calendar = null;
    
    if (date != null) {
      
      GregorianCalendar gcal = new GregorianCalendar();
      gcal.setTime(date);
      
      if (datatypeFactory != null) {
        
        calendar = datatypeFactory.newXMLGregorianCalendar(gcal);
      }
    }
    
    return calendar;
  }
  
  /**
   * Returns the calendar object corresponding to the passed date
   * 
   * @param date A date
   * @return The corresponding calendar
   */
  public static Calendar getCal(Date date) {

    Calendar calendar = null;
    
    if (date != null) {
      
      calendar = Calendar.getInstance();
      calendar.setTime(date);
    }
    
    return calendar;
  }
  
  /**
   * Converts the passed date into a new one whose time corresponds to
   * 23:59:59.999
   * 
   * @param date A date
   * @return The new date
   */
  public static Date setToLastDayMillisecond(Date date) {

    Date newDate = null;
    
    if (date != null) {
      
      Calendar cal = Calendar.getInstance();
      cal.setTime(date);
      cal.set(Calendar.HOUR_OF_DAY, 23);
      cal.set(Calendar.MINUTE, 59);
      cal.set(Calendar.SECOND, 59);
      cal.set(Calendar.MILLISECOND, 999);
      newDate = cal.getTime();
    }
    
    return newDate;
  }
  
  /**
   * Sets the time zone for the passed formatter relatively to the passed
   * request.
   * 
   * @param request The current request
   * @param dateFormatter A date formatter
   */
  public static void setTimeZone(HttpServletRequest request,
      DateFormat dateFormatter) {

    // getting the time zone
    TimeZone timeZone =
        (TimeZone) request.getSession().getAttribute(
            ControllerUtils.TIME_ZONE_ATT);
    
    if (timeZone != null) {
      
      dateFormatter.setTimeZone(timeZone);
    }
  }
}
